--- title: Signal To Noise Ratio for the OpenHSI Camera keywords: fastai sidebar: home_sidebar summary: "Includes an interactive SNR calculator." description: "Includes an interactive SNR calculator." nb_path: "04_snr.ipynb" ---
%time ref_model = Model6SV(tile_type=1.0,wavelength_array = np.linspace(350,820,num=30))
#takes about 20 s, 55 s with Teams running, 40 s with Zoom
ref_model.show()
class Widget_SNR(param.Parameterized):
aperture_mm = param.Number(4, bounds=(1,200),doc="aperture (mm)")
focal_length_mm = param.Number(16,doc="focal length (mm)")
pixel_length_x_μm = param.Number(25, bounds=(1,60),doc="pixel length x (μm)")
pixel_length_y_μm = param.Number(3.45, bounds=(1,60),doc="pixel length y (μm)")
integration_time_ms = param.Number(10, bounds=(5,100), step=1,doc="integration time (ms)")
bandwidth_nm = param.Number(4, bounds=(0.1,20), step=0.1,doc="FWHM bandwidth (nm)")
QE_model = param.ObjectSelector(default="imx174qe", doc="Camera QE model", objects =
[f.split(".")[0] for f in os.listdir("assets") if ".csv" in f])
surface_albedo = param.Number(0.3, bounds=(0,1.0),doc="constant surface albedo reflectance")
# diffraction efficiency unknown
optical_trans_efficiency = param.Number(0.7, bounds=(0.1,1), step=0.05,doc="Optical transmission efficiency")
#solar_zenith_deg = param.Number(0, bounds=(-60,60),doc="solar zenith angle (deg)")
altitude_km = param.Number(0.12, bounds=(0,None),doc="camera altitude (km)")
wavelengths = np.linspace(350,820,num=30)/1e3
ref_model = ref_model
#ref_model = Model6SV(wavelength_array=wavelengths)
@param.depends("altitude_km",watch=True)
def _calc_rad(self):
self.ref_model = Model6SV(alt=self.altitude_km)
@param.depends("aperture_mm","focal_length_mm","pixel_length_x_μm","pixel_length_y_μm",
"integration_time_ms","bandwidth_nm","QE_model","optical_trans_efficiency","surface_albedo")#,"solar_zenith_deg")
def view(self):
self.f_num = self.focal_length_mm / self.aperture_mm
self.A_d = self.pixel_length_x_μm*1e-6 * self.pixel_length_y_μm*1e-6
# interpolation to OpenHSI wavelengths and remove NaNs
self.QE = pd.read_csv(f"assets/{self.QE_model}.csv",names=["wavelength","QE_pct"], header=None)
self.QE["wavelength"] /= 1000
self.QE.insert(0,"type","manufacturer")
self.QE = pd.concat( [ pd.DataFrame({"type":"6SV","wavelength":self.wavelengths}), self.QE] )
self.QE.set_index("wavelength",inplace=True)
self.QE.interpolate(method="cubicspline",axis="index",limit_direction="both",inplace=True)
self.QE = self.QE[self.QE["type"].str.match("6SV")]
self.QE.drop("type", 1,inplace=True)
self.N = self.ref_model.photons * self.integration_time_ms*1e-3 * self.A_d * np.pi/(2*self.f_num)**2 * \
self.bandwidth_nm*1e-3 * self.QE["QE_pct"].to_numpy()/100 * self.optical_trans_efficiency * \
self.surface_albedo #* np.cos(np.deg2rad(self.solar_zenith_deg))
self.table = hv.Table((self.wavelengths*1e3, np.sqrt(self.N)), 'wavelength (nm)', 'SNR')
return hv.Curve(self.table).opts(tools=["hover"],width=600,height=200,ylim=(0,None))
widget = Widget_SNR(name="Interactive SNR Widget")
pn.Row(widget.param,widget.view)
df1 = pd.read_csv("assets/imx174qe.csv",names=["wavelength_nm","QE_pct"], header=None) df2 = pd.read_csv("assets/imx273qe.csv",names=["wavelength_nm","QE_pct"], header=None) df3 = pd.read_csv("assets/cmv2000qe.csv",names=["wavelength_nm","QE_pct"], header=None) ( hv.Curve(df1,label="imx174") hv.Curve(df2,label="imx273") hv.Curve(df3,label="cmv2000") ).opts(width=1000)